<?php
/**
 * etwork ver 0.1
 */
include_once PATH_FRAME.'utility.php';
include_once PATH_FRAME.'smartyFunctions.php';

include_once PATH_FRAME.'libs/Model.php';
include_once PATH_FRAME.'libs/View.php';
include_once PATH_FRAME.'libs/Access.php';
include_once PATH_FRAME.'libs/User.php';

class etwork extends Access 
{
    private $model;
    private $view;
    private $loaders;

    /**
     * 強制的にキャッシュしない
     */
    public $noCaching = false;
    
    /**
     * パーツ出力
     * エラー発生時に出力するものを404ページにしない
     */
    public $isPartContent = false;
    
    /**
     * コンストラクタ
     */
    public function __construct ()
    {
        parent::__construct();
        $this->model  = new Model;
        $this->view   = new View;
        
        //無害化
        $this->sanitizeGPC();
        $this->view->param['system']['start'] = microtime(true);
    }

    /**
     * テンプレート設定
     * @param string templateFileType
     * @param boolean isEdit
     * @param boolean isList
     * @param string cacheID
     */
    public function setTemplate ($templateFileType, $isEdit = false, $isList = false, $cacheID = null)
    {
        $this->view->templateFileType = $templateFileType;
        $this->view->isEdit = $isEdit;
        $this->view->isList = $isList;
        $this->view->cacheID = $cacheID;
    }

    /**
     * テンプレートグループ設定
     */
    function setTemplateGroup ($templateGroup)
    {
        $this->view->templateGroup = $templateGroup;
    }

    /**
     * 処理後クリアするテンプレート
     */
    public function addClearTemplate ($templateFile, $cacheID = null, $compiledID = null, $time = null)
    {
        $this->view->clearTempalteFileAndCacheIdArray[] = array($templateFile, $cacheID, $compiledID, $time);
    }

    /**
     * 強制キャッシュクリア
     * 予め指定されていればそれを削除、無ければ全部削除
     */
    public function clearCache()
    {
        if ($this->view->clearTempalteFileAndCacheIdArray) {
            $this->view->clearAddedCacheFiles();
        } else {
            $this->view->clearAllCache();
        }
    }

    /**
     * パンくず
     */
    public function setPankuzu (Array $array = array())
    {
        $this->view->assign('pankuzu',$array);
    }

    /**
     * ページタイトル
     */
    public function setTitle ($configTitle, $loadParameter = null)
    {
        if (! is_array($configTitle)) $configTitle = array($configTitle);
        $this->view->param['pageName'] = $configTitle;
        $this->view->assign('loadName',$loadParameter);
        
    }

    /**
     * アサイン
     */
    public function viewAssign ($name, $value)
    {
        $this->view->assign($name, $value);
    }

    /**
     * キャッシュ読込
     */
    public function isCached ()
    {
        //強制キャッシュ無し
        if ( $this->noCaching ) {
            $this->view->cacheID = null;
            return false;
        }
        
        //キャッシュ出力非対応
        if (! $this->view->cacheID ) return false;
        
        //キャッシュが存在
        if ( $this->view->isCachedPage() ) return true;
        
        return false;
    }


    private
        $firstTransaction = false,
        $transactionCount = 0,
        $isErrored = false;

    /**
     * ローダースタック追加
     */
    public function addLoader (modelLoader $loader)
    {
        if ($loader->isEdit) $this->transactionCount++;
        $this->loaders[] = $loader;
    }


    /**
     * データベースよりデータ取得
     */
    public function loadData ()
    {
        if (! $this->isAuthorized ) return;

        foreach ($this->loaders as $loader) {

            $this->model->loadModels($loader->model);

            //フォーム編集中はPOSTの値を使う
            if (($loader->isEdit && !empty($this->EX_POST)) || isZero($loader->solo) ) {

                $mapperName = $loader->model."Mapper";
                $mapper = new $mapperName;
                $data = new $loader->model;

                if ($loader->formParameters) {
                    $array = $loader->formParameters;
                    foreach ($this->EX_POST as $k => $v) {
                        if (in_array($k, array('edit','delete','confirm','submit','login'))) {
                            $array[] = $k;
                        }
                        if (strpos($k, '_') === 0) {
                            $array[] = $k;
                        }
                    }
                    
                    $data->fromArray(array_intersect_key($this->EX_POST,array_flip($array)));
                }
                else {
                    $data->fromArray($this->EX_POST);
                }
                $error = $data->isValid();
                if ($error) $this->view->errors = array_merge($this->view->errors, $error);
                
                //不正な値がある
                if ( $this->isErrored || empty($this->EX_POST) || $this->view->errors || isset($this->EX_POST['edit']) ) {
                    if (!$this->isErrored) {
                        $this->isErrored = true;
                        if ($this->firstTransaction) $mapper->rollback();
                    }
                    //編集フォーム
                    $this->view->addResult($loader->returning, $data);
                
                } else if ( isset($this->EX_POST['confirm']) || isset($this->EX_POST['delete']) || isset($this->EX_POST['login']) ) {
                    
                    if (isset($this->view->param['system']['dbstart']))
                        $this->view->param['system']['dbstart'] = microtime(true);
                    
                    if (!$this->firstTransaction) {
                        $this->firstTransaction = true;
                        $mapper->beginTransaction();
                    }
                    $this->transactionCount--;
                    
                    $targetId = $loader->targetId;
                    try {
                        if (isset($this->EX_POST['login'])) {
                            $result = $mapper->login($data);
                            if (!$result) {
                                $mapper->rollback();
                                $this->view->errors['id'] = 'idかパスワードが正しくありません';
                                $this->view->addResult($loader->returning, $data);
                                return;
                            }
                        } else if ($loader->targetCustomFunction) {
                            $function = $loader->targetCustomFunction;
                            $mapper->$function($loader, $data);
                        } else if ($data->$targetId == 0) {
                            $function = $loader->targetInsertFunction;
                            $mapper->$function($loader, $data);
                        } else if (isset($this->EX_POST['delete'])) {
                            $function = $loader->targetDeleteFunction;
                            $mapper->$function($loader, $data);
                        } else {
                            $function = $loader->targetUpdateFunction;
                            $mapper->$function($loader, $data);
                        }
                        
                        if ($this->transactionCount <= 0) {
                            $mapper->commit();
                            
                            $this->view->clearAddedCacheFiles();
                            
                            if ( !empty($this->jumpTo) ) Access::jump($this->jumpTo);
                        } else {
                            $this->view->addResult($loader->returning, $data);
                        }
                        
                    } catch (exception $e) {
                        $mapper->rollback();
                        throw $e;
                    }
    
                } else {
                    //確認フォーム
                    $this->view->isConfirm = true;
                    $this->view->addResult($loader->returning, $data);
                    
                }
                
                
            } else {
                
                $this->view->param['system']['dbstart'] = microtime(true);
    
                $mapperName = $loader->model."Mapper";
                $mapper = new $mapperName;
                
                if ($loader->solo && $loader->solo !== 0) {
                    $function = $loader->targetChoiceFunction;
                    $result = $this->view->addResult($loader->returning, $mapper->$function($loader));
                    
                } else {
                    $function = $loader->targetSelectFunction;
                    $result = $this->view->addResult($loader->returning, $mapper->$function($loader));
                }
                
                if (!$result)
                    $this->view->templateFileType = $this->view->templateGroup = null;
                
                if ($this->view->isList)
                    $this->view->addResult($loader->returning.'_count', $mapper->$function($loader, true));
            }
        }
    }

    /**
     * 出力結果を表示
     */
    public function showFinal ()
    {
        $this->view->assign('member',$this->user);
        if (isset($this->EX_GET)) $this->view->param['get'] = $this->EX_GET;
        
        //不正アクセス
        if (! $this->isAuthorized() ) {
            $this->publishErrorPage(403);
        }
        
        //テンプレート指定無し
        if ( !$this->view->templateFileType && !$this->view->templateGroup ) {
            if ($this->isPartContent) {
                echo('error');
                return;
            }
            $this->publishErrorPage(404);
        }
        
        $this->view->publishHTML();
    }

    /**
     * エラー出力
     */
    function publishErrorPage($errorType)
    {
        $this->view->assign('pankuzu',null);
        $this->view->assign('loadName',null);
        
        if ($errorType == 404) {
        $this->view->param['pageName'] = array('notfound');
            $this->view->templateFile = SMARTY_PAGE_DIR . 'error/notfound';
        } else {
        $this->view->param['pageName'] = array('access','error');
            $this->view->templateFile = SMARTY_PAGE_DIR . 'error/access.error';
        }
        $this->view->publishHTML();
        exit;
    }

}